/*
 * acooly.cn Inc.
 * Copyright (c) 2016 All Rights Reserved.
 * create by zhangpu 
 * date:2016年4月4日
 *
 */
package com.acooly.module.openapi.client.provider.jyt.marshall;

import com.acooly.core.common.exception.BusinessException;
import com.acooly.core.utils.Strings;
import com.acooly.core.utils.validate.Validators;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.provider.jyt.JytConstants;
import com.acooly.module.openapi.client.provider.jyt.OpenAPIClientJytProperties;
import com.acooly.module.openapi.client.provider.jyt.domain.JytApiMessage;
import com.acooly.module.openapi.client.provider.jyt.domain.JytRequest;
import com.acooly.module.openapi.client.provider.jyt.utils.*;
import com.acooly.module.safety.Safes;
import com.acooly.module.safety.key.KeyLoadManager;
import com.acooly.module.safety.signature.SignTypeEnum;
import com.acooly.module.safety.signature.SignerFactory;
import com.acooly.module.safety.support.KeyStoreInfo;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.security.PrivateKey;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;

/**
 * @author zhangpu
 */
@Slf4j
public class JytMarshallSupport {

    @Autowired
    protected OpenAPIClientJytProperties openAPIClientJytProperties;

    @Autowired
    protected SignerFactory signerFactory;

    @Autowired
    private KeyLoadManager keyStoreLoadManager;

    private static JsonMarshallor jsonMarshallor = JsonMarshallor.INSTANCE;

    protected OpenAPIClientJytProperties getProperties() {
        return openAPIClientJytProperties;
    }

    public SignerFactory getSignerFactory() {
        return signerFactory;
    }

    protected String doMarshall(JytRequest source) {
        doVerifyParam(source);
        String requestXml = XmlUtils.toXml(source);
        log.info("请求报文数据: {}", requestXml);
        SortedMap<String, String> datas = Maps.newTreeMap();
        byte[] des_key = DESHelper.generateDesKey() ;
        datas.put(JytConstants.SIGN, doSign(requestXml));
        datas.put(JytConstants.XML_ENC, getXmlEnc(requestXml,des_key));
        byte[] keyEncByte = SignUtils.encryptRSA(des_key,getKeyStore().getCertificate().getPublicKey(),false,"UTF-8");
        String keyEnc = StringHelper.byte2Hex(keyEncByte);
        datas.put(JytConstants.KEY_ENC,keyEnc);
        datas.put(JytConstants.MERCHANT_NO, getProperties().getPartnerId());
        return getRequestStr(datas);
    }

    private String getXmlEnc(String requestXml,byte[] desKey ) {
        String enc_xml = CryptoUtils.desEncryptToHex(requestXml, desKey) ;
        return enc_xml;

    }

    public static String getRequestStr(SortedMap<String, String> requestDataMap) {
        Iterator<Map.Entry<String, String>> entries = requestDataMap.entrySet().iterator();
        StringBuilder returnStr = new StringBuilder();
        while (entries.hasNext()) {
            Map.Entry<String, String> entry = entries.next();
            returnStr.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        if (Strings.isNotBlank(returnStr.toString())) {
            return returnStr.substring(0, returnStr.length() - 1);
        } else {
            return null;
        }
    }

    public String decryptKey(String respKeyEnc,String xmlEnc){
        PrivateKey privateKey = getKeyStore().getPrivateKey();
        byte[] key = null ;
        byte[] enc_key = StringHelper.hexStringToBytes(respKeyEnc) ;

        try {
            key = SignUtils.decryptRSA(enc_key,privateKey, false, "UTF-8") ;
            String xml = CryptoUtils.desDecryptFromHex(xmlEnc, key) ;
            return xml ;
        } catch (Exception e) {
            throw new BusinessException("解密响应报文异常："+e.getMessage());
        }
    }
    /**
     * 将对象转化为String
     *
     * @param object
     * @return
     */

    private String convertString(Object object) {
        if (object == null) {
            return null;
        }
        return object.toString();
    }

    /**
     * 校验参数
     *
     * @param source
     */
    protected void doVerifyParam(JytApiMessage source) {
        try {
            source.doCheck();
            Validators.assertJSR303(source);
        } catch (Exception e) {
            throw new ApiClientException(e.getMessage());
        }
    }

    protected String doSign(String waitForSign) {
        return Safes.getSigner(SignTypeEnum.Cert).sign(waitForSign, getKeyStore());
    }

    /**
     * 验签
     *
     * @param signature
     * @param plain
     * @return
     */
    protected void doVerifySign(String signature, String plain, String partnerId) {
        Safes.getSigner(SignTypeEnum.Cert).verify(plain, getKeyStore(), signature);
    }


    protected KeyStoreInfo getKeyStore() {
        return keyStoreLoadManager.load(JytConstants.PROVIDER_DEF_PRINCIPAL, JytConstants.PROVIDER_NAME);
    }

    protected void beforeMarshall(JytApiMessage message) {

    }

}
